#pragma once
#include <iostream>
#include <filesystem>
#include <vector>
#include <chrono>
#include <iomanip>
#include <algorithm>

#include "event2/http.h"
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/keyvalq_struct.h"

namespace fs = std::filesystem;
using namespace std;

struct FileServerOption
{
	bool enable_directory_search;
	std::vector<std::string> exts;
	std::string base_dirctory;
	std::string base_url;

	virtual std::shared_ptr<FileServerOption> Create() const {
		return make_shared<FileServerOption>(*this);
	}

	virtual ~FileServerOption(){}
};

struct FileInfo
{
	string file_name;
	string file_full_path;
	string extension;
	std::time_t last_write_time;
	uintmax_t file_size;
};

struct DirInfo
{
	string dir_name;
	string dir_full_path;
	std::time_t last_write_time;
};

class FileServer {
public:
	FileServer(FileServerOption& option);

	virtual void QueryServerFiles(evhttp_request* req);

	virtual void QueryServerDirs(evhttp_request* req);

	virtual void RenameServerFile(evhttp_request* req);

	virtual void DeleteServerFile(evhttp_request* req);
	
	FileServerOption* GetOption() {
		return _option.get();
	}
protected:
	shared_ptr<FileServerOption> _option;

	static int SearchFileByExts(fs::path dir_path, unsigned int start, unsigned int limit, vector<string> exts, vector<FileInfo>& file_infos);

	static int SearchDirs(fs::path dir_path, unsigned int start, unsigned int limit, vector<DirInfo>& dir_infos);

	template <typename TP>
	static std::time_t to_time_t(TP tp)
	{
		using namespace std::chrono;
		auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now()
			+ system_clock::now());
		return system_clock::to_time_t(sctp);
	}
};